package com.suke.czx.common.utils;

import cn.hutool.core.util.StrUtil;

import java.math.BigDecimal;

/**
 * 应用模块名称: 工具类
 * 代码描述: 计算工具类
 * copyright: AUZAR ALL RIGHTS RESERVED
 * company: AUZAR
 *
 * @author: 颜米晨
 * @date: 2022/06/12 1:41
 */
public class CalculateUtil {

    /**
     * 除法计算
     * @param dividend 被除数
     * @param divisor 除数
     * @return 商
     */
    public static BigDecimal divide(BigDecimal dividend, BigDecimal divisor) {
        return divide(dividend, divisor, 2);
    }

    /**
     * 除法计算
     * @param dividend 被除数
     * @param divisor 除数
     * @param precision 小数精度
     * @return 商
     */
    public static BigDecimal divide(BigDecimal dividend, BigDecimal divisor, int precision) {
        return divide(dividend, divisor, precision, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 除法计算
     * @param dividend 被除数
     * @param divisor 除数
     * @param precision 小数精度
     * @param roundingMode 舍入方式
     * @return 商
     */
    public static BigDecimal divide(BigDecimal dividend, BigDecimal divisor, int precision, int roundingMode) {
        if (NumUtil.null2Zero(divisor).compareTo(BigDecimal.ZERO) != 0) {
            return NumUtil.null2Zero(dividend, precision, roundingMode).divide(divisor, precision, roundingMode);
        }
        return BigDecimal.ZERO.setScale(precision, roundingMode);
    }

    /**
     * 乘法计算
     * @param multiplicand 被乘数
     * @param multiplier 乘数
     * @return 积
     */
    public static BigDecimal multiply(BigDecimal multiplicand, BigDecimal multiplier) {
        return multiply(multiplicand, multiplier, 2);
    }

    /**
     * 乘法计算
     * @param multiplicand 被乘数
     * @param multiplier 乘数
     * @param precision 小数精度
     * @return 积
     */
    public static BigDecimal multiply(BigDecimal multiplicand, BigDecimal multiplier, int precision) {
        return multiply(multiplicand, multiplier, precision, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 乘法计算
     * @param multiplicand 被乘数
     * @param multiplier 乘数
     * @param precision 小数精度
     * @param roundingMode 舍入方式
     * @return 积
     */
    public static BigDecimal multiply(BigDecimal multiplicand, BigDecimal multiplier, int precision, int roundingMode) {
        return NumUtil.null2Zero(multiplicand, precision, roundingMode).multiply(NumUtil.null2Zero(multiplier, precision, roundingMode)).setScale(precision, roundingMode);
    }

    /**
     * 加法计算
     * @param addend 被加数
     * @param add 加数
     * @return 和
     */
    public static Integer add(Integer addend, Integer add) {
        return NumUtil.null2Zero(addend) + NumUtil.null2Zero(add);
    }

    /**
     * 加法计算
     * @param addend addend 被加数
     * @param add add 加数
     * @return 和
     */
    public static Double add(Double addend, Double add) {
        return NumUtil.null2DoubleZero(StrUtil.toString(addend)) + NumUtil.null2DoubleZero(StrUtil.toString(add));
    }

    /**
     * 加法计算
     * @param addend 被加数
     * @param add 加数
     * @return 和
     */
    public static BigDecimal add(BigDecimal addend, BigDecimal add) {
        return add(addend, add, 2);
    }

    /**
     * 加法计算
     * @param addend 被加数
     * @param add 加数
     * @param precision 小数精度
     * @return 和
     */
    public static BigDecimal add(BigDecimal addend, BigDecimal add, int precision) {
        return add(addend, add, precision, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 加法计算
     * @param addend 被加数
     * @param add 加数
     * @param precision 小数精度
     * @param roundingMode 舍入方式
     * @return 积
     */
    public static BigDecimal add(BigDecimal addend, BigDecimal add, int precision, int roundingMode) {
        return NumUtil.null2Zero(addend, precision, roundingMode).add(NumUtil.null2Zero(add, precision, roundingMode)).setScale(precision, roundingMode);
    }

    /**
     * 减法计算
     * @param minuend 被减数
     * @param subtrahend 减数
     * @return 差
     */
    public static Integer subtract(Integer minuend, Integer subtrahend) {
        return NumUtil.null2Zero(minuend) - NumUtil.null2Zero(subtrahend);
    }

    /**
     * 减法计算
     * @param minuend 被减数
     * @param subtrahend 减数
     * @return 差
     */
    public static BigDecimal subtract(BigDecimal minuend, BigDecimal subtrahend) {
        return subtract(minuend, subtrahend, 2);
    }

    /**
     * 减法计算
     * @param minuend 被减数
     * @param subtrahend 减数
     * @param precision 小数精度
     * @return 差
     */
    public static BigDecimal subtract(BigDecimal minuend, BigDecimal subtrahend, int precision) {
        return subtract(minuend, subtrahend, precision, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 减法计算
     * @param minuend 被减数
     * @param subtrahend 减数
     * @param precision 小数精度
     * @param roundingMode 舍入方式
     * @return 差
     */
    public static BigDecimal subtract(BigDecimal minuend, BigDecimal subtrahend, int precision, int roundingMode) {
        return NumUtil.null2Zero(minuend, precision, roundingMode).subtract(NumUtil.null2Zero(subtrahend, precision, roundingMode)).setScale(precision, roundingMode);
    }

    /**
     * 取余计算
     * @param dividend 被除数
     * @param divisor 除数
     * @return 商和余数组成的数组
     */
    public static BigDecimal[] divideAndRemainder(BigDecimal dividend, BigDecimal divisor) {
        if (divisor != null && divisor.compareTo(BigDecimal.ZERO) != 0) {
            return NumUtil.null2Zero(dividend).divideAndRemainder(divisor);
        }
        return new BigDecimal[]{BigDecimal.ZERO,  BigDecimal.ZERO};
    }

    /**
     * 累加
     * @param add1 加数1
     * @param add2 加数2
     * @param add3 加数3
     * @return 和
     */
    public static BigDecimal mulAdd(BigDecimal add1, BigDecimal add2, BigDecimal add3) {
        return mulAdd(add1, add2, add3, 2);
    }

    /**
     * 累加
     * @param add1 加数1
     * @param add2 加数2
     * @param add3 加数3
     * @param precision 小数精度
     * @return 和
     */
    public static BigDecimal mulAdd(BigDecimal add1, BigDecimal add2, BigDecimal add3, int precision) {
        return mulAdd(add1, add2, add3, precision, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 累加
     * @param add1 加数1
     * @param add2 加数2
     * @param add3 加数3
     * @param precision 小数精度
     * @param roundingMode 舍入方式
     * @return 和
     */
    public static BigDecimal mulAdd(BigDecimal add1, BigDecimal add2, BigDecimal add3, int precision, int roundingMode) {
        return add(add(add1, add2, precision, roundingMode), add3).setScale(precision, roundingMode);
    }

}
